package controller

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"goproject/builder"
	"goproject/commonType"
	"goproject/executor"
	"goproject/logger"
	apiDocMongo "goproject/mongodb/apidoc"
	"goproject/mongodb/record"
	task2 "goproject/mongodb/task"
	"goproject/mongodb/testCase"
	"goproject/mongodb/testMicroservice"
	"net/http"
	"strconv"
	"time"
)

// 初始化 MongoDB 客户端
func initMongoDB() (*mongo.Client, error) {
	uri := "mongodb://root:Zmzzmz010627!@localhost:27017/?authSource=admin"
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	clientOptions := options.Client().ApplyURI(uri)
	client, err := mongo.Connect(ctx, clientOptions)
	if err != nil {
		return nil, err
	}

	err = client.Ping(ctx, nil)
	if err != nil {
		return nil, err
	}

	fmt.Println("Connected to MongoDB!")
	return client, nil
}
func AddTask(c *gin.Context) {
	log := logger.GetLogger()
	log.Info("收到创建任务请求")

	// 从请求中获取task
	var taskDTO commonType.TaskDTO
	if err := c.ShouldBindJSON(&taskDTO); err != nil {
		log.Error("解析任务请求失败", "error", err)
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}
	apiObjectID, err := primitive.ObjectIDFromHex(taskDTO.ApiDoc)
	log.Infof("apidocId: %s", taskDTO.Name)
	if err != nil {
		log.Printf("无效的 ObjectID: %v", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 ObjectID"})
		return
	}
	var task = commonType.Task{
		Name:        taskDTO.Name,
		ApiDoc:      &apiObjectID,
		TraceTree:   taskDTO.TraceTree,
		SelectedReq: taskDTO.SelectedReq,
		FaultConfig: taskDTO.FaultConfig,
		Creator:     taskDTO.Creator,
		CreateTime:  taskDTO.CreateTime,
		NameSpace:   taskDTO.NameSpace,
	}
	client, err := initMongoDB()
	if err != nil {
		log.Error("初始化MongoDB客户端失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Error("断开MongoDB客户端连接失败", "error", err)
			panic(err)
		}
		log.Info("MongoDB客户端连接已断开")
	}()

	db := client.Database("efficientTest")
	taskStore := task2.NewStore(db)

	createdTask, err := taskStore.Create(context.Background(), task)
	if err != nil {
		log.Error("创建任务失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	log.Info("任务创建成功", "taskID", createdTask.ID.Hex())
	c.JSON(200, gin.H{"message": "task created", "taskID": createdTask.ID.Hex()})
}

func ExecTask(c *gin.Context) {
	log := logger.GetLogger()
	log.Info("开始执行任务")

	// 取出taskId
	taskId := c.Query("task_id")
	log.Infof("接收到的任务ID: %s", taskId)

	// 初始化 MongoDB 客户端
	client, err := initMongoDB()
	if err != nil {
		log.Errorf("初始化 MongoDB 客户端失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	log.Info("MongoDB 客户端初始化成功")

	// 获取 MongoDB 数据库和相关集合
	db := client.Database("efficientTest")
	taskStore := task2.NewStore(db)
	testMicroserviceStore := testMicroservice.NewStore(db)
	recordStore := record.NewStore(db)
	testCaseStore := testCase.NewStore(db)

	// 将 taskId 转换为 ObjectID
	taksObjectId, err := primitive.ObjectIDFromHex(taskId)
	if err != nil {
		log.Errorf("将任务ID转换为 ObjectID 失败: %v", err)
		c.JSON(400, gin.H{"error": "Invalid task ID"})
		return
	}

	// 从数据库中获取指定的 task
	task, err := taskStore.Get(context.TODO(), taksObjectId)
	if err != nil {
		log.Errorf("从数据库中获取任务失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	log.Infof("成功获取任务: %v", task)

	// 创建新的测试记录
	record := commonType.Record{
		StartTime: time.Now().Format("2006-01-02 15:04:05"),
		Status:    commonType.StatusRunning,
		TaskID:    task.ID,
		Executor:  "州蛤蜊",
		EndTime:   "",
	}
	record, err = recordStore.Create(context.TODO(), record)
	if err != nil {
		log.Errorf("创建测试记录失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	log.Infof("成功创建测试记录: %v", record)

	// 生成并存储测试微服务
	traceTree := task.TraceTree
	testMicroservicesList, err := builder.GenerateAndStoreTestMicroservice(traceTree, task.FaultConfig, *record.ID, testMicroserviceStore)

	if err != nil {
		log.Errorf("生成并存储测试微服务失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	log.Info("成功生成并存储测试微服务")

	// 为每个测试微服务创建并执行协程
	for _, tm := range testMicroservicesList {
		go func(tm commonType.TestMicroservice) {
			if tm.ID != nil {
				// 创建独立的 context
				ctx := context.Background()
				log.Infof("开始处理测试微服务: %v", tm.ID.Hex())
				executor.HandleTestMicroservices(&ctx, tm, testMicroserviceStore, taskStore, testCaseStore, recordStore)
				log.Infof("完成处理测试微服务: %v", tm.Name)
			} else {
				log.Warn("测试微服务 ID 为空")
			}

		}(tm)
	}

	successResponse := commonType.SuccessResponse{
		Status:  20000,
		Message: "Task started Success",
		Data:    record,
	}
	log.Info("任务启动成功")
	c.JSON(200, successResponse)
}

func GetRecordById(c *gin.Context) {
	log := logger.GetLogger()
	log.Info("开始执行任务")

	// 取出taskId
	recordId := c.Query("record_id")
	log.Infof("接收到的recordID: %s", recordId)

	// 初始化 MongoDB 客户端
	client, err := initMongoDB()
	if err != nil {
		log.Errorf("初始化 MongoDB 客户端失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Errorf("断开 MongoDB 连接失败: %v", err)
			panic(err)
		}
	}()
	// 将 taskId 转换为 ObjectID
	recordObjectId, err := primitive.ObjectIDFromHex(recordId)
	if err != nil {
		log.Errorf("将recordID转换为 ObjectID 失败: %v", err)
		c.JSON(400, gin.H{"error": "Invalid record ID"})
		return
	}

	db := client.Database("efficientTest")
	recordStore := record.NewStore(db)
	record, err := recordStore.Get(context.TODO(), recordObjectId)
	c.JSON(200, record)
}

func GetAllTestCase(c *gin.Context) {
	// 获取所有测试用例
	log := logger.GetLogger()
	log.Info("开始获取所有测试用例")
	client, err := initMongoDB()
	if err != nil {
		log.Errorf("初始化 MongoDB 客户端失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Errorf("断开 MongoDB 连接失败: %v", err)
		}
	}()
	db := client.Database("efficientTest")
	testCaseStore := testCase.NewStore(db)
	testCases, err := testCaseStore.GetAll(context.TODO())
	if err != nil {
		log.Errorf("获取测试用例失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	c.JSON(200, testCases)
}

// 根据id查询testcase
func GetTestCaseById(c *gin.Context) {
	// 取出testcaseId
	testCaseId := c.Query("testcase_id")
	log := logger.GetLogger()
	log.Infof("接收到的testcaseID: %s", testCaseId)
	if testCaseId == "" {
		log.Errorf("testcaseID为空")
		c.JSON(400, gin.H{"error": "Invalid testcase ID"})
		return
	}
	// 初始化 MongoDB 客户端
	client, err := initMongoDB()
	if err != nil {
		log.Errorf("初始化 MongoDB 客户端失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Errorf("断开 MongoDB 连接失败: %v", err)
		}
	}()
	db := client.Database("efficientTest")
	testCaseStore := testCase.NewStore(db)
	testCaseObjectId, err := primitive.ObjectIDFromHex(testCaseId)
	testCase, err := testCaseStore.Get(context.TODO(), testCaseObjectId)
	if err != nil {
		log.Errorf("获取测试用例失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	c.JSON(200, testCase)
}

// 更新测试用例
func UpdateTestCase(c *gin.Context) {
	testCaseId := c.Query("testcase_id")
	log := logger.GetLogger()
	log.Infof("接收到的testcaseID: %s", testCaseId)
	if testCaseId == "" {
		log.Errorf("testcaseID为空")
		c.JSON(400, gin.H{"error": "Invalid testcase ID"})
		return
	}
	// 初始化 MongoDB 客户端
	client, err := initMongoDB()
	if err != nil {
		log.Errorf("初始化 MongoDB 客户端失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Errorf("断开 MongoDB 连接失败: %v", err)
		}
	}()
	db := client.Database("efficientTest")
	testCaseStore := testCase.NewStore(db)
	testCaseObjectId, err := primitive.ObjectIDFromHex(testCaseId)
	testCase, err := testCaseStore.Get(context.TODO(), testCaseObjectId)
	if err != nil {
		log.Errorf("获取测试用例失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	testCase.Response.StatusCode = 888888
	_, err = testCaseStore.Update(context.TODO(), testCase)
	if err != nil {
		log.Errorf("更新测试用例失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	c.JSON(200, testCase)
}

// 新增apiDoc
func AddApiDoc(c *gin.Context) {
	log := logger.GetLogger()
	log.Info("开始新增apiDoc")
	var apiDoc apiDocMongo.ApiDoc
	var ApiDocDTOs []commonType.ApiDocDTO
	if err := c.ShouldBindJSON(&ApiDocDTOs); err != nil {
		log.Errorf("解析请求体失败: %v", err)
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}
	// 将 ApiDocDTOs 序列化为 JSON 字符串
	jsonContent, err := json.Marshal(ApiDocDTOs)
	if err != nil {
		log.Errorf("序列化请求体失败: %v", err)
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}
	apiDoc.Content = string(jsonContent)

	client, err := initMongoDB()
	if err != nil {
		log.Error("初始化MongoDB客户端失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Error("断开MongoDB客户端连接失败", "error", err)
			panic(err)
		}
		log.Info("MongoDB客户端连接已断开")
	}()

	db := client.Database("efficientTest")
	apiDocStore := apiDocMongo.NewStore(db)
	apiDoc, err = apiDocStore.Create(context.TODO(), apiDoc)
	if err != nil {
		log.Errorf("新增apiDoc失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	c.JSON(200, apiDoc)
}

// 分页获取task
func GetTaskByPage(c *gin.Context) {
	log := logger.GetLogger()
	log.Info("开始获取task")
	client, err := initMongoDB()
	if err != nil {
		log.Error("初始化MongoDB客户端失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Error("断开MongoDB客户端连接失败", "error", err)
			panic(err)
		}
		log.Info("MongoDB客户端连接已断开")
	}()

	db := client.Database("efficientTest")
	store := task2.NewStore(db)
	// 获取分页参数
	pageStr := c.DefaultQuery("page", "1")
	pageSizeStr := c.DefaultQuery("page_size", "10")

	page, err := strconv.Atoi(pageStr)
	if err != nil || page < 1 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid page parameter"})
		return
	}

	pageSize, err := strconv.Atoi(pageSizeStr)
	if err != nil || pageSize < 1 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid page_size parameter"})
		return
	}

	// 计算跳过的文档数
	skip := (page - 1) * pageSize

	// 查询数据库
	var tasks []commonType.Task
	findOptions := options.Find()
	findOptions.SetSkip(int64(skip))
	findOptions.SetLimit(int64(pageSize))

	tasks, err = store.GetByPage(context.TODO(), skip, pageSize)
	if err != nil {
		log.Errorf("查询数据库失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	log.Infof("任务长度：%d", len(tasks))

	sumTask, err := store.GetAll(context.TODO())

	// 返回结果
	c.JSON(200, gin.H{"total": len(sumTask), "tasks": tasks})
}

// 查看task所对应的测试记录
func GetRecordByTaskId(c *gin.Context) {
	// 获取分页参数
	pageStr := c.DefaultQuery("page", "1")
	pageSizeStr := c.DefaultQuery("page_size", "10")

	page, err := strconv.Atoi(pageStr)
	if err != nil || page < 1 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid page parameter"})
		return
	}

	pageSize, err := strconv.Atoi(pageSizeStr)
	if err != nil || pageSize < 1 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid page_size parameter"})
		return
	}

	// 计算跳过的文档数
	skip := (page - 1) * pageSize

	log := logger.GetLogger()
	log.Info("开始获取task")
	client, err := initMongoDB()
	if err != nil {
		log.Error("初始化MongoDB客户端失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Error("断开MongoDB客户端连接失败", "error", err)
			panic(err)
		}
		log.Info("MongoDB客户端连接已断开")
	}()
	db := client.Database("efficientTest")
	recordStore := record.NewStore(db)
	taskId := c.Query("task_id")
	taksObjectId, err := primitive.ObjectIDFromHex(taskId)
	if err != nil {
		log.Errorf("将任务ID转换为 ObjectID 失败: %v", err)
		c.JSON(400, gin.H{"error": "Invalid task ID"})
		return
	}
	recordList, err := recordStore.GetByTaskID(context.TODO(), taksObjectId, skip, pageSize)
	if err != nil {
		log.Errorf("查询数据库失败: %v", err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	sumsRecord, err := recordStore.GetByTaskID(context.TODO(), taksObjectId, 0, 0)
	total := len(sumsRecord)
	c.JSON(http.StatusOK, gin.H{"total": total, "records": recordList})
}

// 根据测试记录id获取请求追踪树
func GetTraceByRecordId(c *gin.Context) {
	/*
			1. 根据recordId 定位到 task
		    2. 取出task的traceTree
	*/
	log := logger.GetLogger()
	log.Info("开始获取请求追踪树")

	recordId := c.Query("record_id")

	client, err := initMongoDB()
	if err != nil {
		log.Error("初始化MongoDB客户端失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Error("断开MongoDB客户端连接失败", "error", err)
			panic(err)
		}
		log.Info("MongoDB客户端连接已断开")
	}()
	db := client.Database("efficientTest")
	recordStore := record.NewStore(db)
	taskStore := task2.NewStore(db)
	recordObjecId, err := primitive.ObjectIDFromHex(recordId)
	if err != nil {
		log.Error("objectId转换失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
	}
	targetRecord, err := recordStore.Get(context.Background(), recordObjecId)
	if err != nil {
		log.Error("目标record获取失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
	}
	targetTask, err := taskStore.Get(context.Background(), *targetRecord.TaskID)
	if err != nil {
		log.Error("目标task获取失败", "error", err)
		c.JSON(500, gin.H{"error": err.Error()})
	}
	c.JSON(http.StatusOK, targetTask.TraceTree)
}

// 根据recordId获取各个微服务的运行状态
func GetMSStatusByRecordId(c *gin.Context) {
	log := logger.GetLogger()
	log.Info("开始获取请求追踪树")
	recordId := c.Query("record_id")
	client, err := initMongoDB()
	if err != nil {
		log.Error()
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Error("断开MongoDB客户端连接失败", "error", err)
			panic(err)
		}
		log.Info("MongoDB客户端连接已断开")
	}()
	db := client.Database("efficientTest")
	recordObjecId, err := primitive.ObjectIDFromHex(recordId)
	testMicroserviceStore := testMicroservice.NewStore(db)
	testMicroservices, _ := testMicroserviceStore.GetAllByRecordId(context.Background(), recordObjecId)
	// Create a slice to hold the output
	var serviceStatuses []commonType.ServiceStatus

	// Extract the needed fields
	for _, ms := range testMicroservices {
		serviceStatus := commonType.ServiceStatus{
			ServiceName: ms.Name,
			Status:      ms.TestStatus,
		}
		serviceStatuses = append(serviceStatuses, serviceStatus)
	}
	c.JSON(http.StatusOK, testMicroservices)
}

// 根据MSId 获取MS的运行情况
func GetMSRunDetailByMSId(c *gin.Context) {
	log := logger.GetLogger()
	log.Info("开始获取请求追踪树")
	msId := c.Query("ms_id")
	// 获取分页参数
	pageStr := c.DefaultQuery("page", "1")
	pageSizeStr := c.DefaultQuery("page_size", "10")

	page, err := strconv.Atoi(pageStr)
	if err != nil || page < 1 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid page parameter"})
		return
	}

	pageSize, err := strconv.Atoi(pageSizeStr)
	if err != nil || pageSize < 1 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid page_size parameter"})
		return
	}

	// 计算跳过的文档数
	skip := (page - 1) * pageSize

	client, err := initMongoDB()
	if err != nil {
		log.Error()
	}
	defer func() {
		if err := client.Disconnect(context.TODO()); err != nil {
			log.Error("断开MongoDB客户端连接失败", "error", err)
			panic(err)
		}
		log.Info("MongoDB客户端连接已断开")
	}()
	db := client.Database("efficientTest")
	testCaseStore := testCase.NewStore(db)
	microsercice_id, _ := primitive.ObjectIDFromHex(msId)
	testCases, err := testCaseStore.GetListByTestMicroserviceId(context.Background(), microsercice_id, skip, pageSize)
	if err != nil {
		log.Error("获取测试用例失败", "error", err)
	}
	sumTestCases, err := testCaseStore.GetListByTestMicroserviceId(context.Background(), microsercice_id, 0, 0)
	total := len(sumTestCases)
	c.JSON(http.StatusOK, gin.H{"total": total, "testCases": testCases})
}
